import pygame
import Configurable
import Timekeeper
import Item
import Effect
import Util
import G
import Config
import copy
import sys
import os

def spawn(base_powerup, pos):
   if isinstance(base_powerup, str):
      base_powerup = G.powerup_dict[base_powerup]
   base_powerup['startpos'] = pos
   new_powerup = Configurable.instantiate(base_powerup)
   G.powerups.add(new_powerup)
   return new_powerup

class Powerup(pygame.sprite.Sprite, Configurable.Configurable, Timekeeper.Timekeeper):
   runtime_vars = ('move_xbuffer',
                   'move_ybuffer',
                   'velocity',
                   'item_real')

   __slots__ = ('imagepath',
                'item',
                'effect',
                'value') + runtime_vars
   
   def __init__(self, name, imagepath, startpos=(0,0), value=0, item=None, effect=None,
                description=""):
      pygame.sprite.Sprite.__init__(self)
      Configurable.Configurable.__init__(self, locals())
      self.image, self.rect = Util.load_image(self.imagepath)
      self.rect.center = startpos
      if effect is not None:
         if isinstance(effect, dict):
            self.effect = Configurable.instantiate(effect)
         else:
            self.effect = effect
      if item is not None:
         if Util.is_sequence(item):
            item_real = copy.deepcopy(G.items[item[0]])
            item_real['level'] = item[1]
            self.item_real = Configurable.instantiate(item_real)
         else:
            self.item_real = Configurable.instantiate(G.items[item])
      else:
         self.item_real = None
      self.move_xbuffer = 0.0
      self.move_ybuffer = 0.0
      self.velocity = [0, 2 * Config.scroll_rate]
   
   def apply(self, ship):
      ship.score += self.value
      if self.item_real is not None:
         self.item_real.add_item(ship)
         if not Config.nova:
            ship.equip_item(self.item_real)
      if self.effect is not None:
         self.effect.start(ship)

   @classmethod
   def from_file(cls, items):
      vars_dict = dict()
      other_vars = dict()
      vars = cls.config_vars()
      for key, val in items:
         if key in vars:
            vars_dict[key] = Util.str_convert(val)
         else:
            other_vars[key] = Util.str_convert(val)
      if other_vars['type'].lower() == 'effect':
         effect_type = eval('Effect.' + other_vars['effect_type'])
         effect_vars = dict()
         needed = effect_type.config_vars()
         for key in other_vars.keys():
            if key in needed:
               effect_vars[key] = other_vars[key]
         effect_type.check_missing(effect_vars)
         effect_vars['type'] = effect_type
         vars_dict['effect'] = effect_vars
      cls.check_missing(vars_dict)
      vars_dict['type'] = cls
      return vars_dict
   
   def move(self, move_x, move_y):
      self.rect.move_ip(move_x, move_y)
      if not self.rect.colliderect(G.game.screenrect):
         self.kill()
      pickups = pygame.sprite.spritecollide(self, G.friendly_ships, False)
      if len(pickups) > 0:
         self.apply(pickups[0])
         self.kill()
   
   def update(self):
      frame_time = self.frame()
      self.move_xbuffer += self.velocity[0] * frame_time
      self.move_ybuffer += self.velocity[1] * frame_time
      move_x, self.move_xbuffer = divmod(self.move_xbuffer, 1.0)
      move_y, self.move_ybuffer = divmod(self.move_ybuffer, 1.0)
      self.move(int(move_x), int(move_y))
